

import java.util.Hashtable;
import java.util.Timer;
import java.util.TimerTask;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;

import player.MP3Metadata;
import state.State;
import tool.KeyCode;
import tool.ScreenUtils;
import boot.Boot;
import function.ChainMp3;
import function.search.SearchKeyHandler;
import graphics.Background;
import graphics.BootColor;
import graphics.ModeChooser;
import graphics.MultiLineText;
import graphics.SearchChoiceInput;
import graphics.SearchInput;

public class MainScreen extends Canvas implements CommandListener {

	private Graphics graphics;
	private int Y_TEXT_OFFSET = 17;

	private final Command searchCommand = new Command("Search", Command.OK, 1);
	private final Command pauseCommand = new Command("Pause", Command.ITEM, 1);
	private final Command playCommand = new Command("Play", Command.ITEM, 1);
	private final Command cancelSearchCommand = new Command("Cancel",
			Command.EXIT, 1);
	private final Command AuthorCommand = new Command("Author", Command.EXIT, 1);
	// private final Command titleCommand = new Command("Title", Command.EXIT,
	// 1);

	private SearchKeyHandler searchKeyHandler = null;
	private Hashtable displayedCommand = new Hashtable();
	private SearchInput searchInput = null;
	private SearchChoiceInput searchChoiceInput = null;
	private ChainMp3 searchChoices = null;
	private Timer alertTimer;
	private MultiLineText text = null;
	private MultiLineText alert = null;
	private Background background = null;
	private ModeChooser modeChooser = new ModeChooser();
	private MP3Metadata metadata;
	private boolean mainButtonPushed = false;

	public MainScreen() throws Throwable {
		setCommandListener(this);
		text = new MultiLineText(0, graphics);
		background = new Background();
	}

	protected void paint(Graphics g) {
		graphics = g;

		ScreenUtils.setBlackBackground(graphics);
		background.repaint(graphics);

		if (Boot.state().equals(State.MODE_CHOICE)) {
			modeChooser.repaint(graphics);
			drawAlert();
		} else if (Boot.state().equals(State.SEARCH_CHOICE)) {
			if (searchChoiceInput == null) {
				searchChoiceInput = new SearchChoiceInput(searchChoices);
			}
			searchChoiceInput.repaint(graphics);
		} else {
			mainPaint();
		}
	}

	private void mainPaint() {

		graphics.setColor(BootColor.BLACK);
		graphics.drawRect(0, 0, 240 - 6, 27);

		if (searchInput != null) {
			searchInput.repaint(graphics);
		} else if (alert != null) {
			drawAlert();
		} else if (metadata != null) {
			drawCurrentMetadata();
		}
	}

	private void drawAlert() {
		if (alert == null) {
			return;
		}
		alert.repaint(graphics, BootColor.ORANGE);
	}

	public void keyPressed(int keyCode) {

		if ((mainButtonPushed) && (keyCode == KeyCode.ASTERISK)) {
			Boot.getInstance().lockScreen();
			Boot.state().remove(State.SEARCH_ENGAGED);
		} else if (Boot.state().equals(State.MODE_CHOICE)) {
			modeChooser.keyPressed(keyCode);
		} else if (Boot.state().equals(State.SEARCH_CHOICE)) {
			if (searchChoiceInput == null) {
				searchChoiceInput = new SearchChoiceInput(searchChoices);
			}
			searchChoiceInput.processKey(keyCode);
		} else if (Boot.state().equals(State.SEARCH_ENGAGED)) {
			searchKeyHandler.processKey(keyCode);
		} else {
			Boot.getInstance().keyPressed(keyCode);
		}

		Boot.repaint();
	}

	public void drawCurrentMetadata() {
		if (Boot.state().equals(State.AUTHOR_DISPLAY)) {
			text.setContent("by " + metadata.getAuthor());
			text.repaint(graphics, BootColor.CRAZY_ORANGE);
		} else {
			text.setContent(metadata.getTitle());
			int color = BootColor.WHITE;
			if (Boot.state().equals(State.GOLDEN_TUNE)) {
				color = BootColor.GOLDEN;
			}
			text.repaint(graphics, color);
		}
	}

	public void alert(String message, int timeout) {
		alert = new MultiLineText(0, graphics);
		alert.setContent(message);
		repaint();

		if (alertTimer != null) {
			alertTimer.cancel();
		}
		alertTimer = new Timer();
		alertTimer.schedule(new TimerTask() {
			public void run() {

				alert = null;
				alertTimer = null;
				repaint();
			}
		}, timeout);
	}

	// todo remove
	public void setSearchAvailable(boolean available) {
		if (available) {
			secureAddCommand(searchCommand);
		} else {
			secureRemoveCommand(searchCommand);
		}
	}

	public void commandAction(Command command, Displayable dis) {

		if (command == cancelSearchCommand) {
			Boot.getInstance().cancelSearch();
		} else if (command == playCommand) {
			onMainButtonPushed();
			Boot.getInstance().playPlayer();
		} else if (command == pauseCommand) {
			onMainButtonPushed();
			Boot.getInstance().pausePlayer();
		} else if (command == searchCommand) {
			onMainButtonPushed();
			if ((Boot.state().equals(State.SEARCH_ENGAGED))
					|| (Boot.state().equals(State.MODE_CHOICE))) {
				alert("Ignored", 2000);
			} else {
				Boot.getInstance().searchEngaged();
			}
		} else if (command == AuthorCommand) {
			Boot.addState(State.AUTHOR_DISPLAY);
			new Timer().schedule(new TimerTask() {

				public void run() {
					Boot.removeState(State.AUTHOR_DISPLAY);
					handleCommands();
					repaint();
				}
			}, 3000);
		}
		handleCommands();
		repaint();
	}

	private void onMainButtonPushed() {
		mainButtonPushed = true;
		new Timer().schedule(new TimerTask() {

			public void run() {
				mainButtonPushed = false;
			}
		}, 1000);
	}

	public void rebootSearch() {
		searchKeyHandler = null;
		searchChoiceInput = null;
	}

	private void secureAddCommand(Command command) {
		if (displayedCommand.get(command) == null) {
			displayedCommand.put(command, "");
			addCommand(command);
		}
	}

	private void secureRemoveCommand(Command command) {
		if (displayedCommand.get(command) != null) {
			displayedCommand.remove(command);
			removeCommand(command);
		}
	}

	public void searchDisplayUpdate(char value) {
		searchInput.charInput(value);
	}

	public void shiftSearchCursor() {
		searchInput.shiftCursor(1);
	}

	public void createSearchInput(boolean value) {
		if (value) {
			searchInput = new SearchInput(this, 2);
			searchInput.setColors(BootColor.BLACK, BootColor.ORANGE);
			searchInput.setCursorAt(0);
			searchInput.setY(Y_TEXT_OFFSET);
		} else {
			searchInput = null;
		}
	}

	public void setSearchChoices(ChainMp3 result) {
		searchChoices = result;
		searchChoiceInput = new SearchChoiceInput(result);
	}

	public void handleCommands() {

		secureRemoveCommand(cancelSearchCommand);
		secureRemoveCommand(playCommand);
		secureRemoveCommand(pauseCommand);
		secureRemoveCommand(AuthorCommand);

		if (Boot.state().equals(State.PLAY_MP3)) {
			secureAddCommand(pauseCommand);
		} else if (Boot.state().equals(State.PAUSE_MP3)) {
			secureAddCommand(playCommand);
		}

		if ((Boot.state().equals(State.SEARCH_ENGAGED))
				|| (Boot.state().equals(State.SEARCH_CHOICE))) {
			secureAddCommand(cancelSearchCommand);
		} else if (Boot.state().equals(State.IDLE)) {
			secureAddCommand(searchCommand);
		}

		if ((Boot.state().equals(State.PLAY_MP3))
				|| (Boot.state().equals(State.PAUSE_MP3))) {
			if (Boot.state().equals(State.AUTHOR_DISPLAY)) {
				// secureAddCommand(titleCommand);
			} else {
				secureAddCommand(AuthorCommand);
			}
		}
	}

	public void showSearchInput() {
		rebootSearch();
		createSearchInput(true);
		if (searchKeyHandler == null) {
			searchKeyHandler = new SearchKeyHandler();
		}
	}

	public void setMetadata(MP3Metadata someMetadata) {
		metadata = someMetadata;
	}
}
